package anim;

import java.util.Collections;
import java.util.Vector;

import vis.Viewport;

public class Animation {
	private Viewport vport = null;
	private Vector<Frame> frames = new Vector<Frame>();
	private volatile boolean running = false;
	private int t = 0;
	private int end = 0;
	private int cf = 0;
	private boolean resetAtAnd = false;
	
	public Animation(Viewport vport)
	{
		this.vport = vport;
	}
	
	public void addFrame(Frame f, int delay)
	{
		if(!running)
		{
			frames.add(f);
			f.setTime(end + delay);
			end += delay;
		}
	}
	
	public void startAnim()
	{
		if(frames.size() == 0) return;
		Collections.sort(frames);
		System.out.println(frames);
		end = frames.lastElement().getTime();
		//t = 0;
		seekTo(0);
		System.out.println("Starting animation... " + t + " - " + end);
		playAnim();
	}
	
	public void stopAnim()
	{
		running = false;
	}
	
	private void playAnim()
	{
		if(frames.size() == 0) return;
		if(vport == null) return;
		if(running) return;
		
		running = true;
		
		Thread th = new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(running)
				{
					
					if(t > end) { System.out.println("Animation ended"); running = false; }
					if(cf < frames.size())
					{
						while(frames.get(cf).getTime() <= t)
						{
							frames.get(cf).doFrame();
							cf++;
							vport.repaint();
							if(cf >= frames.size()) { cf = frames.size() - 1; break; }
						}
					}
					t++;
					
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {}
				}
				
				if(t >= end && resetAtAnd) seekTo(0);
			}
		});
		
		th.start();
	}
	
	public void seekTo(int time)
	{
		if(time > t)
		{
			for(; t < time; t++)
			{
				while(frames.get(cf).getTime() <= t)
				{
					frames.get(cf).doFrame();
					cf++;
					if(cf >= frames.size()) break;
				}
			}
			vport.repaint();
		}
		else if(time < t)
		{
			for(; t >= 0; t--)
			{
				while(frames.get(cf).getTime() >= t)
				{
					frames.get(cf).undoFrame();
					cf--;
					if(cf < 0) { cf = 0; break; }
				}
			}
			t = time;
			vport.repaint();
		}
	}
	
	public void clear()
	{
		if(running) return;
		frames.clear();
		t = end = cf = 0;
	}
	
	public boolean isRunning()
	{
		return running;
	}
	
	public void seekToEnd()
	{
		seekTo(end);
	}
}
